﻿using UnityEditor;
using UnityEngine;
using System.IO;
using System.Security.Cryptography;
using System.Collections.Generic;

namespace XLua
{
    public class Packager
    {
        public static string platform = string.Empty;
        static List<string> paths = new List<string>();
        static List<string> files = new List<string>();
        static List<AssetBundleBuild> maps = new List<AssetBundleBuild>();

        ///-----------------------------------------------------------
        static string[] exts = { ".txt", ".xml", ".lua", ".assetbundle", ".json" };
        static bool CanCopy(string ext)
        {   //能不能复制
            foreach (string e in exts)
            {
                if (ext.Equals(e)) return true;
            }
            return false;
        }

        /// <summary>
        /// 载入素材
        /// </summary>
        static UnityEngine.Object LoadAsset(string file)
        {
            if (file.EndsWith(".lua")) file += ".txt";
            return AssetDatabase.LoadMainAssetAtPath("Assets/LuaFramework/Examples/Builds/" + file);
        }

        [MenuItem("LuaFramework/Build All Resource", false, 100)]
        static void BuildAllResources()
        {
            BuildLuaResources();
            BuildAssetResource();
            CopyRaw();
            string ns = EditorSettings.projectGenerationRootNamespace.ToLower();
            if (ns.Equals("mainapp"))
            {
                //			PackagerCovers();
                //			PackagerCharacters();
            }
            BuildFileIndex();
        }

        //将文件夹中的每个文件build成单独的一个assetbundle
        //	[MenuItem("LuaFramework/MainApp - Build Covers", false, 121)]
        //	static void PackagerCovers(){
        //		string folder =  Application.dataPath + "/MainApp/Covers";//要build的文件夹
        //		if(Directory.Exists(folder)){
        //			string streaming = Application.streamingAssetsPath + "/mainapp/covers";//build到streaming assets下面
        //			if(Directory.Exists(streaming)) 
        //				Directory.Delete(streaming,true);
        //			Directory.CreateDirectory(streaming);
        //			var files = Directory.GetFiles(folder,"*.jpg",SearchOption.TopDirectoryOnly);
        //
        //			List<AssetBundleBuild> maps = new List<AssetBundleBuild>();
        //
        //			for(int i = 0 ;i<files.Length;++i){
        //				string file = files[i];
        //				FileInfo info = new FileInfo(file);
        //
        //				AssetBundleBuild build = new AssetBundleBuild();
        //				build.assetBundleName = "cover_"+info.Name.Substring(0,info.Name.Length-4)+".unity3d";
        //				build.assetNames = new string[]{
        //					"Assets/MainApp/Covers/"+info.Name
        //				};
        //				maps.Add(build);
        //			}
        //			if(maps.Count>0){
        //				BuildPipeline.BuildAssetBundles(streaming, maps.ToArray(), BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);
        //				AssetDatabase.Refresh();
        //
        //				//复制一份到项目外面
        //				if(EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS || EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android){
        //					string dest = Application.dataPath.Substring(0,Application.dataPath.Length-7)+"/Exports/"+Packager.GetFolderByBuildTarget(EditorUserBuildSettings.activeBuildTarget)+"/"+EditorSettings.projectGenerationRootNamespace.ToLower();
        //					dest+="/covers";
        //					if (Directory.Exists(dest))
        //						Directory.Delete(dest, true);
        //
        //					Packager.CopyDirectory(streaming,dest,true);
        //				}
        //
        //			}else{
        //				Directory.Delete(streaming,true);
        //			}
        //		}
        //	}

        //将一个文件夹中的所有资源Build到一个assetbundle中
        //	[MenuItem("LuaFramework/MainApp - Build Characters", false, 124)]
        //	static void PackagerCharacters(){
        //		string folder =  Application.dataPath + "/MainApp/Characters";
        //		if(Directory.Exists(folder)){
        //			string streaming = Application.streamingAssetsPath + "/mainapp/characters";
        //			if(Directory.Exists(streaming)) 
        //				Directory.Delete(streaming,true);
        //			Directory.CreateDirectory(streaming);
        //
        //			List<AssetBundleBuild> maps = new List<AssetBundleBuild>();
        //			string[] folders = Directory.GetDirectories(folder);
        //			for(int i = 0 ;i<folders.Length;++i){
        //				string f = folders[i];
        //				var files = Directory.GetFiles(f,"*.*",SearchOption.TopDirectoryOnly);
        //
        //				AssetBundleBuild build = new AssetBundleBuild();
        //				string fName = f.Substring(f.LastIndexOf("/")+1);
        //				build.assetBundleName = fName+".unity3d";
        //
        //				List<string> names = new List<string>();
        //				for(int j = 0 ;j<files.Length;++j){
        //					string file = files[j];
        //					FileInfo info = new FileInfo(file);
        //					if(info.Name.LastIndexOf(".DS_Store")==-1 && info.Name.LastIndexOf(".meta")==-1){
        //						names.Add("Assets/MainApp/Characters/"+fName+"/"+info.Name);
        //					}
        //				}
        //				build.assetNames = names.ToArray();
        //				maps.Add(build);
        //			}
        //
        //			if(maps.Count>0){
        //				BuildPipeline.BuildAssetBundles(streaming, maps.ToArray(), BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);
        //				AssetDatabase.Refresh();
        //
        //				//复制一份到项目外面
        //				if(EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS || EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android){
        //					string dest = Application.dataPath.Substring(0,Application.dataPath.Length-7)+"/Exports/"+Packager.GetFolderByBuildTarget(EditorUserBuildSettings.activeBuildTarget)+"/"+EditorSettings.projectGenerationRootNamespace.ToLower();
        //					dest+="/characters";
        //					if (Directory.Exists(dest))
        //						Directory.Delete(dest, true);
        //
        //					Packager.CopyDirectory(streaming,dest,true);
        //				}
        //
        //			}else{
        //				Directory.Delete(streaming,true);
        //			}
        //		}
        //	}


        [MenuItem("LuaFramework/MainApp - CopyExportsToProj", false, 125)]
        static void CopyExportToProj()
        {
#if ZIP || zip
		string exportsFolder = Application.dataPath.Substring(0,Application.dataPath.Length-7)+"/Exports/"+Packager.GetFolderByBuildTarget(EditorUserBuildSettings.activeBuildTarget);

#if UNITY_IOS
		string iOSProjectPath = Application.dataPath + "/../proj.ios_mac/Data/Raw";
		if(Directory.Exists(iOSProjectPath) && Directory.Exists(exportsFolder)){
			if(Directory.Exists(iOSProjectPath+"/lua")) Directory.Delete(iOSProjectPath+"/lua",true);
			if(Directory.Exists(iOSProjectPath+"/mainapp")) Directory.Delete(iOSProjectPath+"/mainapp",true);
			if(Directory.Exists(iOSProjectPath+"/mainappraw")) Directory.Delete(iOSProjectPath+"/mainappraw",true);

			if(File.Exists(iOSProjectPath+"/lua.zip")) File.Delete(iOSProjectPath+"/lua.zip");
			if(File.Exists(iOSProjectPath+"/mainapp.zip")) File.Delete(iOSProjectPath+"/mainapp.zip");
			if(File.Exists(iOSProjectPath+"/mainappraw.zip")) File.Delete(iOSProjectPath+"/mainappraw.zip");
			if(File.Exists(iOSProjectPath+"/mainapp.txt")) File.Delete(iOSProjectPath+"/mainapp.txt");

			var dirs1 = new string[]{exportsFolder+"/lua"};
			var dirs2 = new string[]{exportsFolder+"/mainapp"};
			var dirs3 = new string[]{exportsFolder+"/mainappraw"};
			ZipUtility.Zip(dirs1,iOSProjectPath+"/lua.zip");
			ZipUtility.Zip(dirs2,iOSProjectPath+"/mainapp.zip");
			ZipUtility.Zip(dirs3,iOSProjectPath+"/mainappraw.zip");

			if(File.Exists(exportsFolder+"/mainapp.txt")){
				File.Copy(exportsFolder+"/mainapp.txt",iOSProjectPath+"/mainapp.txt");
			}
		}

#elif UNITY_ANDROID
		string androidStudioProjectPath = Application.dataPath + "/../proj.android/app/src/main/assets";
		if(Directory.Exists(exportsFolder) && Directory.Exists(androidStudioProjectPath)){
		if(Directory.Exists(androidStudioProjectPath+"/lua")) Directory.Delete(androidStudioProjectPath+"/lua",true);
		if(Directory.Exists(androidStudioProjectPath+"/mainapp")) Directory.Delete(androidStudioProjectPath+"/mainapp",true);
		if(Directory.Exists(androidStudioProjectPath+"/mainappraw")) Directory.Delete(androidStudioProjectPath+"/mainappraw",true);

		if(File.Exists(androidStudioProjectPath+"/lua.zip")) File.Delete(androidStudioProjectPath+"/lua.zip");
		if(File.Exists(androidStudioProjectPath+"/mainapp.zip")) File.Delete(androidStudioProjectPath+"/mainapp.zip");
		if(File.Exists(androidStudioProjectPath+"/mainappraw.zip")) File.Delete(androidStudioProjectPath+"/mainappraw.zip");
		if(File.Exists(androidStudioProjectPath+"/mainapp.txt")) File.Delete(androidStudioProjectPath+"/mainapp.txt");

		var dirs1 = new string[]{exportsFolder+"/lua"};
		var dirs2 = new string[]{exportsFolder+"/mainapp"};
		var dirs3 = new string[]{exportsFolder+"/mainappraw"};
		ZipUtility.Zip(dirs1,androidStudioProjectPath+"/lua.zip");
		ZipUtility.Zip(dirs2,androidStudioProjectPath+"/mainapp.zip");
		ZipUtility.Zip(dirs3,androidStudioProjectPath+"/mainappraw.zip");

		if(File.Exists(exportsFolder+"/mainapp.txt")){
			File.Copy(exportsFolder+"/mainapp.txt",androidStudioProjectPath+"/mainapp.txt");
			}
		}
#endif
#endif
        }




        [MenuItem("LuaFramework/MainApp - Calculate Update", false, 126)]
        static void CalculateUpdate()
        {
            string exportFolder = Application.dataPath.Substring(0, Application.dataPath.Length - 7) + "/Exports/";
            if (!Directory.Exists(exportFolder))
                return;

            string updateZip = exportFolder + (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS ? "iOS/update.zip" : "Android/update.zip");
            if (File.Exists(updateZip))
            {
                File.Delete(updateZip);
            }
            string oldMd5File = exportFolder + (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS ? "ios.txt" : "android.txt");
            string currFolder = exportFolder + (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS ? "iOS/" : "Android/");
            string newMd5File = exportFolder + (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS ? "iOS/mainapp.txt" : "Android/mainapp.txt");
            if (!File.Exists(oldMd5File) || !File.Exists(newMd5File))
                return;

            string[] lines = File.ReadAllLines(oldMd5File);
            Dictionary<string, string> oldMd5KV = new Dictionary<string, string>();
            foreach (string line in lines)
            {
                if (line.Length > 2)
                {
                    string[] temp = line.Split('|');
                    if (temp.Length > 1)
                    {
                        oldMd5KV[temp[0]] = temp[1];
                    }
                }
            }


            lines = File.ReadAllLines(newMd5File);
            Dictionary<string, string> newMd5KV = new Dictionary<string, string>();
            foreach (string line in lines)
            {
                if (line.Length > 2)
                {
                    string[] temp = line.Split('|');
                    if (temp.Length > 1)
                    {
                        newMd5KV[temp[0]] = temp[1];
                    }
                }
            }


            string tempFold = exportFolder + "_temp/";
            if (Directory.Exists(tempFold))
            {
                Directory.Delete(tempFold, true);
            }
            Directory.CreateDirectory(tempFold);
            int count = 0;
            foreach (string path in newMd5KV.Keys)
            {
                if (!oldMd5KV.ContainsKey(path) || oldMd5KV[path] != newMd5KV[path])
                {
                    string f = tempFold + path.Substring(0, path.LastIndexOf("/"));
                    if (!Directory.Exists(f))
                        Directory.CreateDirectory(f);
                    File.Copy(currFolder + path, tempFold + path, true);
                    ++count;
                }
            }
            //创建 zip
            string pwd = "";
            ZipUtility.Zip(Directory.GetDirectories(tempFold), updateZip, pwd);
            UnityEngine.Debug.Log("有" + count + "个更新文件");

            Directory.Delete(tempFold, true);
        }


        string ReverseStr(string text)
        {
            char[] charArray = text.ToCharArray();
            System.Array.Reverse(charArray);
            return new string(charArray);
        }

        [MenuItem("LuaFramework/MainApp - Md5 And Calculate Update", false, 127)]
        static void Md5AndCalculateUpdate()
        {
            BuildFileIndex();
            CalculateUpdate();
        }



        [MenuItem("LuaFramework/Build Lua", false, 102)]
        static void BuildLuaResources()
        {
            string streamPath = Application.streamingAssetsPath + "/lua";
            if (Directory.Exists(streamPath))
            {
                Directory.Delete(streamPath, true);
            }
            Directory.CreateDirectory(streamPath);
            AssetDatabase.Refresh();

            maps.Clear();

            HandleLuaBundle();

            string resPath = "Assets/StreamingAssets";
            BuildPipeline.BuildAssetBundles(resPath, maps.ToArray(), BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);

            string tempDir = Application.dataPath + "/" + AppConst.LuaTempDir;
            if (File.Exists(tempDir + ".meta"))
                File.Delete(tempDir + ".meta");
            if (Directory.Exists(tempDir))
                Directory.Delete(tempDir, true);

            if (File.Exists(Application.streamingAssetsPath + "/StreamingAssets"))
                File.Delete(Application.streamingAssetsPath + "/StreamingAssets");
            if (File.Exists(Application.streamingAssetsPath + "/StreamingAssets.meta"))
                File.Delete(Application.streamingAssetsPath + "/StreamingAssets.meta");
            if (File.Exists(Application.streamingAssetsPath + "/StreamingAssets.manifest"))
                File.Delete(Application.streamingAssetsPath + "/StreamingAssets.manifest");
            if (File.Exists(Application.streamingAssetsPath + "/StreamingAssets.manifest.meta"))
                File.Delete(Application.streamingAssetsPath + "/StreamingAssets.manifest.meta");

            AssetDatabase.Refresh();

            //加密
            byte[] byte_key = { 0x38, 0x2A, 0x28, 0x61, 0x79, 0x74, 0x62, 0x34 };
            byte[] byte_iv = { 0x3F, 0x2D, 0x2F, 0x79, 0x54, 0xA6, 0xE2, 0x32 };

            string[] files = Directory.GetFiles(streamPath);
            for (int i = 0; i < files.Length; ++i)
            {
                string f = files[i];
                if (f.EndsWith(".manifest") || f.EndsWith(".meta")) continue;

                var data = File.ReadAllBytes(f);
                using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
                {
                    des.Key = byte_key;
                    des.IV = byte_iv;

                    // 创建一个内存流来存储加密后的数据
                    using (var memoryStream = new MemoryStream())
                    {
                        // 创建一个加密流来执行加密操作
                        using (var cryptoStream = new CryptoStream(memoryStream, des.CreateEncryptor(), CryptoStreamMode.Write))
                        {
                            // 将数据写入加密流
                            cryptoStream.Write(data, 0, data.Length);
                            cryptoStream.FlushFinalBlock();
                            var resultData = memoryStream.ToArray();
                            File.WriteAllBytes(f, resultData);
                        }
                    }
                }
            }



            //复制当前项目的脚本到Export目录中
            if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS || EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
            {
                string destFolder = Application.dataPath.Substring(0, Application.dataPath.Length - 7) + "/Exports/" + GetFolderByBuildTarget(EditorUserBuildSettings.activeBuildTarget) + "/lua";
                if (Directory.Exists(destFolder))
                    Directory.Delete(destFolder, true);
                Directory.CreateDirectory(destFolder);

                string ns = EditorSettings.projectGenerationRootNamespace.ToLower();
                bool isMainApp = ns.Equals("mainapp") || string.IsNullOrEmpty(ns);

                files = Directory.GetFiles(streamPath);
                for (int i = 0; i < files.Length; ++i)
                {
                    string f = files[i];

                    if (f.IndexOf("lua_" + EditorSettings.projectGenerationRootNamespace.ToLower()) > 0)
                    {

                        if (f.EndsWith(".meta") || f.EndsWith(".manifest")) continue;

                        File.Copy(f, destFolder + "/" + Path.GetFileName(f), true);
                    }
                    else if (isMainApp)
                    {

                        if (f.EndsWith(".meta") || f.EndsWith(".manifest")) continue;

                        File.Copy(f, destFolder + "/" + Path.GetFileName(f), true);
                    }
                }

                if (!isMainApp)
                {
                    if (File.Exists(destFolder + "/lua.unity3d")) File.Delete(destFolder + "/lua.unity3d");
                    if (File.Exists(destFolder + "/lua.unity3d.manifest")) File.Delete(destFolder + "/lua.unity3d.manifest");
                }
            }
        }

        [MenuItem("LuaFramework/Build Selected Assets", false, 105)]
        static void BuildSelectedAssets()
        {
            Object[] objs = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
            if (objs != null)
            {
                maps.Clear();
                Dictionary<string, List<string>> _temp = new Dictionary<string, List<string>>();
                foreach (var obj in objs)
                {
                    string dirPath = AssetDatabase.GetAssetOrScenePath(obj);
                    if (string.IsNullOrEmpty(dirPath) == false)
                    {
                        if (Directory.Exists(dirPath))
                        {
                            //遍历下面所有的文件
                            string[] files = Directory.GetFiles(Application.dataPath + dirPath.Substring(6), "*.*", SearchOption.AllDirectories);
                            foreach (var file in files)
                            {
                                var url = file.Substring(file.IndexOf(dirPath));
                                if (file.EndsWith(".meta") == false && file.EndsWith(".DS_Store") == false)
                                {
                                    AssetImporter importer = AssetImporter.GetAtPath(url);
                                    if (importer != null && !string.IsNullOrEmpty(importer.assetBundleName))
                                    {
                                        if (!_temp.ContainsKey(importer.assetBundleName))
                                        {
                                            _temp[importer.assetBundleName] = new List<string>();
                                        }
                                        _temp[importer.assetBundleName].Add(url);
                                        importer.assetBundleName = null;

                                        CollectDepends(url, _temp);
                                    }
                                }
                            }
                        }
                        else if (File.Exists(dirPath))
                        {
                            var url = dirPath.Substring(dirPath.IndexOf(dirPath));
                            if (dirPath.EndsWith(".meta") == false && dirPath.EndsWith(".DS_Store") == false)
                            {
                                AssetImporter importer = AssetImporter.GetAtPath(url);
                                if (importer != null && !string.IsNullOrEmpty(importer.assetBundleName))
                                {
                                    if (!_temp.ContainsKey(importer.assetBundleName))
                                    {
                                        _temp[importer.assetBundleName] = new List<string>();
                                    }
                                    _temp[importer.assetBundleName].Add(url);
                                    importer.assetBundleName = null;

                                    CollectDepends(url, _temp);
                                }
                            }
                        }
                    }
                }



                foreach (string bundleName in _temp.Keys)
                {
                    AssetBundleBuild build = new AssetBundleBuild();
                    build.assetBundleName = bundleName;

                    string[] all = AssetDatabase.GetAssetPathsFromAssetBundle(bundleName);
                    var v = _temp[bundleName];
                    for (int i = 0; i < all.Length; ++i)
                    {
                        var a = all[i];
                        AssetImporter importer = AssetImporter.GetAtPath(a);
                        if (importer != null && importer.assetBundleName == bundleName)
                        {
                            _temp[bundleName].Add(a);
                        }
                    }
                    build.assetNames = _temp[bundleName].ToArray();
                    maps.Add(build);
                }
                if (maps.Count > 0)
                {
                    string resPath = "Assets/StreamingAssets/" + EditorSettings.projectGenerationRootNamespace.ToLower();
                    BuildPipeline.BuildAssetBundles(resPath, maps.ToArray(), BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);

                    //还原assetbundlename
                    foreach (AssetBundleBuild abb in maps)
                    {
                        foreach (string url in abb.assetNames)
                        {
                            AssetImporter importer = AssetImporter.GetAtPath(url);
                            importer.assetBundleName = abb.assetBundleName;
                        }
                    }
                    maps.Clear();
                    AssetDatabase.Refresh();
                }
            }

        }
        static void CollectDepends(string filePath, Dictionary<string, List<string>> _temp)
        {
            string[] files = AssetDatabase.GetDependencies(filePath, true);
            foreach (var url in files)
            {
                if (url.EndsWith(".meta") == false && url.EndsWith(".DS_Store") == false)
                {
                    AssetImporter importer = AssetImporter.GetAtPath(url);
                    if (importer != null && !string.IsNullOrEmpty(importer.assetBundleName))
                    {
                        if (!_temp.ContainsKey(importer.assetBundleName))
                        {
                            _temp[importer.assetBundleName] = new List<string>();
                        }
                        _temp[importer.assetBundleName].Add(url);
                        importer.assetBundleName = null;
                        //					CollectDepends(file,_temp);
                    }
                }
            }
        }

        [MenuItem("LuaFramework/Build Asset Resource", false, 103)]
        /// <summary>
        /// 生成绑定素材
        /// </summary>
        static void BuildAssetResource()
        {
            string streamPath = Application.streamingAssetsPath + "/" + EditorSettings.projectGenerationRootNamespace.ToLower();
            if (Directory.Exists(streamPath))
            {
                var files = Directory.GetFiles(streamPath, "*.*", SearchOption.TopDirectoryOnly);
                for (int i = 0; i < files.Length; ++i)
                {
                    if (File.Exists(files[i]))
                    {
                        File.Delete(files[i]);
                    }
                }
            }
            else
            {
                Directory.CreateDirectory(streamPath);
            }

            AssetDatabase.Refresh();
            BuildPipeline.BuildAssetBundles(streamPath, BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);
            AssetDatabase.Refresh();

            //复制一份到项目外面
            if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS || EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
            {
                string dest = Application.dataPath.Substring(0, Application.dataPath.Length - 7) + "/Exports/" + GetFolderByBuildTarget(EditorUserBuildSettings.activeBuildTarget) + "/" + EditorSettings.projectGenerationRootNamespace.ToLower();
                if (Directory.Exists(dest))
                {
                    string[] allFiles = Directory.GetFiles(dest, "*.*");
                    for (int i = 0; i < allFiles.Length; ++i)
                    {
                        File.Delete(allFiles[i]);
                    }
                }
                CopyDirectory(streamPath, dest, false);
            }
        }

        [MenuItem("LuaFramework/Copy Raw Folder", false, 104)]
        static void CopyRaw()
        {
            string streamPath = Application.streamingAssetsPath + "/" + EditorSettings.projectGenerationRootNamespace.ToLower() + "raw";
            if (Directory.Exists(streamPath))
            {
                if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS || EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android)
                {
                    string dest = Application.dataPath.Substring(0, Application.dataPath.Length - 7) + "/Exports/" + GetFolderByBuildTarget(EditorUserBuildSettings.activeBuildTarget) + "/" + EditorSettings.projectGenerationRootNamespace.ToLower();
                    dest = dest + "raw";
                    if (Directory.Exists(dest))
                        Directory.Delete(dest, true);
                    CopyDirectory(streamPath, dest, true);
                }
            }
        }

        public static string GetFolderByBuildTarget(BuildTarget tar)
        {
            if (tar == BuildTarget.Android)
                return "Android";
            if (tar == BuildTarget.iOS)
                return "iOS";
            return "PC";
        }

        public static void CopyDirectory(string sourceDirName, string destDirName, bool copySubDirs)
        {
            // Get the subdirectories for the specified directory.
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);

            if (!dir.Exists)
            {
                return;
            }

            DirectoryInfo[] dirs = dir.GetDirectories();
            // If the destination directory doesn't exist, create it.
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }

            // Get the files in the directory and copy them to the new location.
            FileInfo[] files = dir.GetFiles();
            foreach (FileInfo file in files)
            {
                if (file.Name.EndsWith(".meta")) continue;

                if (file.FullName.EndsWith(".manifest"))
                {
                    string folder = Directory.GetParent(file.FullName).Name;
                    if (!file.FullName.EndsWith(folder + ".manifest"))
                    {
                        continue;
                    }
                }

                string temppath = Path.Combine(destDirName, file.Name);
                file.CopyTo(temppath, true);
            }

            // If copying subdirectories, copy them and their contents to new location.
            if (copySubDirs)
            {
                foreach (DirectoryInfo subdir in dirs)
                {
                    string temppath = Path.Combine(destDirName, subdir.Name);
                    CopyDirectory(subdir.FullName, temppath, copySubDirs);
                }
            }
        }

        static void AddBuildMap(string bundleName, string pattern, string path)
        {
            string[] files = Directory.GetFiles(path, pattern, AppConst.LuaBundleByFolder ? SearchOption.TopDirectoryOnly : SearchOption.AllDirectories);
            if (files.Length == 0) return;

            for (int i = 0; i < files.Length; i++)
            {
                files[i] = files[i].Replace('\\', '/');
            }
            System.Array.Sort<string>(files, delegate (string x, string y)
            {
                if (x.Length > y.Length) return 1;
                else if (x.Length < y.Length) return -1;
                return 0;
            });

            AssetBundleBuild build = new AssetBundleBuild();
            build.assetBundleName = bundleName;
            build.assetNames = files;
            maps.Add(build);
        }


        /// <summary>
        /// 处理Lua代码包
        /// </summary>
        static void HandleLuaBundle()
        {
            string streamDir = Application.dataPath + "/" + AppConst.LuaTempDir;
            if (!Directory.Exists(streamDir)) Directory.CreateDirectory(streamDir);

            string[] srcDirs = { Application.dataPath + "/Lua", Application.dataPath + "/XLua/Lua" };
            for (int i = 0; i < srcDirs.Length; i++)
            {
                CopyLuaBytesFiles(srcDirs[i], streamDir);
            }

            if (AppConst.LuaBundleByFolder)
            {
                //2. 按文件夹生成lua bundle
                string[] dirs = Directory.GetDirectories(streamDir, "*", SearchOption.AllDirectories);
                for (int i = 0; i < dirs.Length; i++)
                {
                    string name = dirs[i].Replace(streamDir, string.Empty);
                    name = name.Replace('\\', '_').Replace('/', '_');
                    name = "lua/lua" + name.ToLower() + AppConst.ExtName;

                    string path = "Assets" + dirs[i].Replace(Application.dataPath, "");
                    AddBuildMap(name, "*.bytes", path);
                }
                AddBuildMap("lua/lua" + AppConst.ExtName, "*.bytes", "Assets/" + AppConst.LuaTempDir);
            }
            else
            {
                //1. 当前项目中所有的lua生成一个lua bundle
                string bundleName = "lua/lua" + AppConst.ExtName;
                AddBuildMap(bundleName, "*.bytes", "Assets/" + AppConst.LuaTempDir);
            }




            //-------------------------------处理非Lua文件----------------------------------
            //        string luaPath = AppDataPath + "/StreamingAssets/lua/";
            //        for (int i = 0; i < srcDirs.Length; i++) {
            //            paths.Clear(); files.Clear();
            //            string luaDataPath = srcDirs[i].ToLower();
            //            Recursive(luaDataPath);
            //            foreach (string f in files) {
            //				if (f.EndsWith(".meta") || f.EndsWith(".lua") || f.EndsWith(".DS_Store") || f.EndsWith(".iml")|| f.EndsWith(".bat")) continue;
            //                string newfile = f.Replace(luaDataPath, "");
            //                string path = Path.GetDirectoryName(luaPath + newfile);
            //                if (!Directory.Exists(path)) Directory.CreateDirectory(path);
            //
            //                string destfile = path + "/" + Path.GetFileName(f);
            //                File.Copy(f, destfile, true);
            //            }
            //        }
            AssetDatabase.Refresh();
        }

        public static void CopyLuaBytesFiles(string sourceDir, string destDir, bool appendext = true, string searchPattern = "*.lua", SearchOption option = SearchOption.AllDirectories)
        {
            if (!Directory.Exists(sourceDir))
            {
                return;
            }

            string[] files = Directory.GetFiles(sourceDir, searchPattern, option);
            int len = sourceDir.Length;

            if (sourceDir[len - 1] == '/' || sourceDir[len - 1] == '\\')
            {
                --len;
            }

            for (int i = 0; i < files.Length; i++)
            {
                string str = files[i].Remove(0, len);
                string dest = destDir + str;
                if (appendext) dest += ".bytes";
                string dir = Path.GetDirectoryName(dest);
                Directory.CreateDirectory(dir);
                File.Copy(files[i], dest, true);
            }
        }

        /// <summary>
        /// md5 streamingAssets下面所有文件
        /// </summary>
        [MenuItem("LuaFramework/Md5 Files", false, 200)]
        static void BuildFileIndex()
        {
            string resPath = AppDataPath + "/StreamingAssets/";

            ///-------------------删除一些多余的文件------------------
            if (File.Exists(resPath + "StreamingAssets"))
            {
                File.Delete(resPath + "StreamingAssets");
            }
            if (File.Exists(resPath + "StreamingAssets.manifest"))
            {
                File.Delete(resPath + "StreamingAssets.manifest");
            }
            if (File.Exists(resPath + "StreamingAssets.meta"))
            {
                File.Delete(resPath + "StreamingAssets.meta");
            }
            if (File.Exists(resPath + "StreamingAssets.manifest.meta"))
            {
                File.Delete(resPath + "StreamingAssets.manifest.meta");
            }

            ///----------------------创建文件列表-----------------------
            resPath = Application.streamingAssetsPath + "/";
            BuildFileIndex(resPath);

            if (EditorUserBuildSettings.activeBuildTarget == BuildTarget.Android || EditorUserBuildSettings.activeBuildTarget == BuildTarget.iOS)
            {
                resPath = Application.dataPath.Substring(0, Application.dataPath.Length - 7) + "/Exports/" + GetFolderByBuildTarget(EditorUserBuildSettings.activeBuildTarget);
                if (!Directory.Exists(resPath)) return;
                resPath += "/";
                BuildFileIndex(resPath);
            }
        }
        static void BuildFileIndex(string resPath)
        {
            string rootNS = EditorSettings.projectGenerationRootNamespace.ToLower();
            string newFilePath = resPath + rootNS + "md5" + ".txt";
            if (File.Exists(newFilePath)) File.Delete(newFilePath);

            paths.Clear(); files.Clear();
            Recursive(resPath);

            FileStream fs = new FileStream(newFilePath, FileMode.CreateNew);
            StreamWriter sw = new StreamWriter(fs);
            for (int i = 0; i < files.Count; i++)
            {
                string file = files[i];
                if (file.EndsWith(".meta") || file.Contains(".DS_Store"))
                    continue;

                if (file.EndsWith(".manifest"))
                {
                    string folder = Directory.GetParent(file).Name;
                    if (!file.EndsWith(folder + ".manifest"))
                    {
                        continue;
                    }
                }

                string md5 = XLua.LuaUtil.md5file(file);
                string value = file.Replace(resPath, string.Empty);
                if (value.IndexOf("/") > 0) //只md5 文件夹下面的，不处理StreamingAssets目录下面的文件
                {
                    sw.WriteLine(value + "|" + md5 + "|" + GetFileSize(file));
                }
            }
            sw.Close(); fs.Close();
            AssetDatabase.Refresh();
        }


        static long GetFileSize(string path)
        {
            using (FileStream fs = new FileStream(path, FileMode.Open))
            {
                return fs.Length;
            }
        }



        //	[MenuItem("LuaFramework/Md5 Export IOS Files", false, 512)]
        //	static void BuildExportIOSFileIndex() {
        //		BuildExportFileIndex(BuildTarget.iOS);
        //	}
        //	[MenuItem("LuaFramework/Md5 Export Android Files", false, 513)]
        //	static void BuildExportAndroidFileIndex() {
        //		BuildExportFileIndex(BuildTarget.Android);
        //	}


        //	static void BuildExportFileIndex(BuildTarget target) {
        //		
        //		string resPath = Application.dataPath.Substring(0,Application.dataPath.Length-7)+"/Exports/"+GetFolderByBuildTarget(target)+"/";
        //
        //		///----------------------创建文件列表-----------------------
        //		string newFilePath = resPath + "/files.txt";
        //		if (File.Exists(newFilePath)) File.Delete(newFilePath);
        //
        //		paths.Clear(); files.Clear();
        //		Recursive(resPath);
        //
        //		FileStream fs = new FileStream(newFilePath, FileMode.CreateNew);
        //		StreamWriter sw = new StreamWriter(fs);
        //		for (int i = 0; i < files.Count; i++) {
        //			string file = files[i];
        //			if (file.EndsWith(".meta") || file.Contains(".DS_Store") 
        //				|| file.IndexOf("google-services")>-1 
        //				|| file.IndexOf("GoogleService-Info")>-1) 
        //				continue;
        //
        //			string ext = Path.GetExtension(file);
        //
        //			string md5 = Util.md5file(file);
        //			string value = file.Replace(resPath, string.Empty);
        //			if(value.IndexOf("Framework")==0){
        //				value = value.Replace("Framework","lua");
        //			}
        //
        //			sw.WriteLine(value + "|" + md5);
        //		}
        //		sw.Close(); fs.Close();
        //		AssetDatabase.Refresh();
        //	}



        /// <summary>
        /// 数据目录
        /// </summary>
        static string AppDataPath
        {
            get { return Application.dataPath.ToLower(); }
        }

        /// <summary>
        /// 遍历目录及其子目录
        /// </summary>
        static void Recursive(string path)
        {
            string[] names = Directory.GetFiles(path);
            string[] dirs = Directory.GetDirectories(path);
            foreach (string filename in names)
            {
                string ext = Path.GetExtension(filename);
                if (ext.Equals(".meta")) continue;
                files.Add(filename.Replace('\\', '/'));
            }
            foreach (string dir in dirs)
            {
                paths.Add(dir.Replace('\\', '/'));
                Recursive(dir);
            }
        }

        static void UpdateProgress(int progress, int progressMax, string desc)
        {
            string title = "Processing...[" + progress + " - " + progressMax + "]";
            float value = (float)progress / (float)progressMax;
            EditorUtility.DisplayProgressBar(title, desc, value);
        }

    }
}